package log

import (
	"log"
	"sync"
)

var (
	defaultLogger ILogger
	loggers       sync.Map

	writers sync.Map
)

func Init(option *LoggerOption, writers ...IWriter) {
	if option == nil {
		option = &LoggerOption{Name: "default", Caller: true, CallerSkip: 2}
	}

	var err error
	defaultLogger, err = CreateLogger(option, writers...)
	if err != nil {
		panic(err)
	}

	return
}

func Final() {
	loggers.Range(func(key, value any) bool {
		l, ok := value.(*logger)
		if ok && l != nil {
			l.Destroy()
		}
		return true
	})

	writers.Range(func(key, value any) bool {
		w, ok := value.(IWriter)
		if ok && w != nil {
			w.Destroy()
		}
		return true
	})
}

func Debug(args ...any) {
	defaultLogger.Debug(args...)
}

func Debugf(format string, args ...any) {
	defaultLogger.Debugf(format, args...)
}

func Info(args ...any) {
	defaultLogger.Info(args...)
}

func Infof(format string, args ...any) {
	defaultLogger.Infof(format, args...)
}

func Warn(args ...any) {
	defaultLogger.Warn(args...)
}

func Warnf(format string, args ...any) {
	defaultLogger.Warnf(format, args...)
}

func Error(args ...any) {
	defaultLogger.Error(args...)
}

func Errorf(format string, args ...any) {
	defaultLogger.Errorf(format, args...)
}

func Default() ILogger {
	return defaultLogger
}

func GetLogger(name string) (ILogger, bool) {
	v, ok := loggers.Load(name)
	if !ok {
		return nil, false
	}
	l, ok := v.(ILogger)
	if !ok || l == nil {
		return nil, false
	}
	return l, true
}

func MustGetLogger(name string) ILogger {
	l, ok := GetLogger(name)
	if !ok {
		log.Panicf("logger[%s] not exist", name)
	}
	return l
}

func GetWriter(name string) (IWriter, bool) {
	v, ok := writers.Load(name)
	if !ok {
		return nil, false
	}
	w, ok := v.(IWriter)
	if !ok || w == nil {
		return nil, false
	}
	return w, true
}

func MustGetWriter(name string) IWriter {
	w, ok := GetWriter(name)
	if !ok {
		log.Panicf("writer[%s] not exist", name)
	}
	return w
}
